home *** CD-ROM | disk | FTP | other *** search
/ 9-Digit Zip Code Directory / 9-Digit Zip Code Directory (American Business Information) (ABIZIP-12).ISO / z4src.zip / BSSTR2.C < prev    next >
C/C++ Source or Header  |  1995-06-08  |  11KB  |  405 lines

  1. //----------------------------------------------------------------------------
  2. //                            MODULE DESCRIPTION
  3. //
  4. //  Module:    bsstr2.c
  5. //   Title:    Base library
  6. //  Notice:    John M. Weeder
  7. //                 Copyright (c) 1993. All rights reserved.
  8. //             This module contains proprietary information and should be 
  9. //                treated as confidential.
  10. //
  11. //----------------------------------------------------------------------------
  12. //                           MAINTENANCE HISTORY
  13. //
  14. // $Workfile$
  15. // $Revision$
  16. //   $Author$
  17. //     $Date$
  18. //      $Log$    
  19. //
  20. //----------------------------------------------------------------------------
  21. //                             MODULE NARRATIVE
  22. //
  23. //
  24. //    This module contains utility string functions.
  25. //
  26. //    The code in this module should be written entirely in C. 
  27. //    Do not use any C++ constructs.
  28. //
  29. //    This module is portable to:
  30. //        DOS 3.X+
  31. //        MS Windows 3.X+
  32. //        OS/2 2.X+
  33. //        OS/2 2.0 PM
  34. //        SCO UNIX.
  35. //
  36. //    The following compilers are supported:
  37. //        MSC 6.0A
  38. //        MSC/C++ 7.0
  39. //        Borland C++ 3.1 for DOS
  40. //        Borland C++ 1.0 for OS/2 2.X
  41. //        SCO UNIX cc
  42. //
  43. //----------------------------------------------------------------------------
  44. #include <bs.h>
  45.  
  46.  
  47. //----------------------------------------------------------------------------
  48. //   Description:    Check if all characters in a string are numeric.
  49. //    Parameters:    pcsz        String
  50. //       Returns:    TRUE if all characters are numeric
  51. //----------------------------------------------------------------------------
  52. BOOL FN_E strisnumeric(PCSZ pcsz)
  53. {
  54.     return strisvalid(pcsz, "[0-9]*");
  55. }
  56.  
  57.  
  58. //----------------------------------------------------------------------------
  59. //   Description:   Check if all characters in a string are numeric or if
  60. //                  the second character is an A,B, or C
  61. //    Parameters:    pcsz        String
  62. //       Returns:    TRUE if all characters are numeric
  63. //----------------------------------------------------------------------------
  64. //BOOL FN_E strisnumeric2(PCSZ pcsz)
  65. //{
  66. //    return strisvalid(pcsz, "[aAbBcC0-9]*");
  67. //}
  68.  
  69.  
  70.  
  71. //----------------------------------------------------------------------------
  72. //   Description:    Check if all characters in a string are valid phone 
  73. //             TT characters (0..9 and A..Z except Q and Z)
  74. //    Parameters:    pcsz        String
  75. //       Returns:    TRUE if all characters are valid
  76. //----------------------------------------------------------------------------
  77. BOOL FN_E strisphone(PCSZ pcsz)
  78. {
  79.     return strisvalid(pcsz, "[a-zA-Z0-9~qQzZ]+");
  80. }
  81.  
  82.  
  83. //----------------------------------------------------------------------------
  84. //   Description:    Check if all characters in a string are valid.
  85. //    Parameters:    pcsz            String
  86. //                        pcszValid    Valid characters for string.
  87. //                                        This string is a regular expression style
  88. //                                        statement, but it is very limited in complexity.
  89. //                                        Only ASCII chracters are allowed!
  90. //                                        No nested expressions are allowed.
  91. //                                        This algoritm is not recursive, so
  92. //                                        "a*a" is NOT allowed! ("a?a" is allowed).
  93. //       Returns:    TRUE if all characters are numeric
  94. //----------------------------------------------------------------------------
  95. BOOL FN_E strisvalid(PCSZ pcsz, PCSZ pcszValid)
  96. {
  97.     BYTE bFlag[128];
  98.     BOOL fFlag;
  99.     BOOL fOneOrMore;
  100.     BOOL fMany;
  101.     SIZET cCount;
  102.     CHAR chStart, chEnd;
  103.  
  104.     Assert(pcsz && pcszValid);
  105.     while (pcszValid[0])
  106.         {
  107.         switch (toascii(pcszValid[0]))
  108.             {
  109.             case '\\':                            // Escape character
  110.                 pcszValid++;
  111.                 Assert(pcszValid[0]);
  112.                 // Fall through
  113.  
  114.             default:                                // Exact match
  115.                 if (toascii(pcsz[0]) != toascii(pcszValid[0]))
  116.                     return FALSE;
  117.                 pcsz++;
  118.                 pcszValid++;
  119.                 break;
  120.  
  121.             case '?':                            // Match any single
  122.                 if (!pcsz[0])                    // If no match, done
  123.                     return FALSE;
  124.                 pcsz++;                            // Skip character
  125.                 return TRUE;
  126.  
  127.             case '[':
  128.                 pcszValid++;                    // Skip open bracket
  129.                 fFlag = TRUE;
  130.                 memset(bFlag, 0, sizeof(bFlag));
  131.                 while (pcszValid[0] != ']')
  132.                     {
  133.                     Assert(pcszValid[0]);
  134.                     if (pcszValid[0] == '~')
  135.                         {
  136.                         Assert(fFlag);
  137.                         fFlag = FALSE;
  138.                         pcszValid++;
  139.                         }
  140.         else
  141.             {
  142.             if (pcszValid[0] == '\\')
  143.                 {
  144.                 pcszValid++;
  145.                 Assert(pcszValid[0]);
  146.                 }
  147.             chStart = toascii(pcszValid[0]);
  148.             pcszValid++;
  149.             if (pcszValid[0] == '-')
  150.                 {
  151.                pcszValid++;
  152.                 Assert(pcszValid[0]);
  153.                if (pcszValid[0] == '\\')
  154.                    {
  155.                    pcszValid++;
  156.                    Assert(pcszValid[0]);
  157.                    }
  158.                chEnd = toascii(pcszValid[0]);
  159.            pcszValid++;
  160.         for (; chStart <= chEnd; ++chStart)
  161.                     bFlag[chStart] = (BYTE)fFlag;
  162.                 }
  163.             else
  164.                 bFlag[chStart] = (BYTE)fFlag;
  165.             }
  166.         }
  167.     pcszValid++;                    // Skip closing bracket
  168.                 fOneOrMore = FALSE;
  169.                 fMany = FALSE;
  170.                 if (pcszValid[0] == '+')    // Allow one or more characters to match
  171.                     {
  172.                     fOneOrMore = TRUE;
  173.                     pcszValid++;
  174.                     }
  175.                 else if (pcszValid[0] == '*')
  176.                     {
  177.                     fMany = TRUE;                // Allow any number of characters
  178.                     pcszValid++;
  179.                     }
  180.                 if (fOneOrMore || fMany)
  181.                     {
  182.                     cCount = 0;
  183.                     while (pcsz[0] && bFlag[toascii(pcsz[0])])
  184.                         {
  185.                         pcsz++;
  186.                         cCount++;
  187.                         }
  188.                     if (!cCount && fOneOrMore)
  189.                         return FALSE;            // Need at least one character match
  190.                     }
  191.                 else                                // Only looking for a single charcter
  192.                     {
  193.                     if (!pcsz[0] || !bFlag[toascii(pcsz[0])])
  194.                         return FALSE;
  195.                     pcsz++;
  196.                     }
  197.                 break;
  198.             }
  199.         }
  200.     return pcsz[0] == '\0';
  201. }
  202.  
  203.  
  204. //----------------------------------------------------------------------------
  205. //   Description:    Extract a long value from a string. Both signed and 
  206. //                          unsigned longs are recognized. 
  207. //    Parameters:    psz            String to validate.
  208. //                        pl                Pointer to store long value at. If null, don't
  209. //                                        save value. 0L if return value is FALSE.
  210. //       Returns:    TRUE if string represented a valid long.
  211. //----------------------------------------------------------------------------
  212. BOOL FN_E strvalidlong(PCSZ psz, PLONG pl)
  213. {
  214. static PSZ pszLong  = "2147483647";
  215.     BOOL fMinus = FALSE;
  216.     BOOL fHex = FALSE;
  217.     SIZET cDigits = 0;
  218.     SIZET cZero = 0;
  219.     CHAR szBuf[11];
  220.     PSZ pszBuf = szBuf;
  221.  
  222.     if (pl)                                        // Set default value
  223.         pl[0] = 0L;
  224.  
  225.     if (!psz || !psz[0])                        // String must not be empty
  226.         return FALSE;
  227.  
  228.     psz = strskipws(psz);                    // Skip leading whitespace
  229.  
  230.     if (psz[0] == '0' && toupper(psz[1]) == 'X')
  231.         {
  232.         fHex = TRUE;
  233.         psz += 2;
  234.         }
  235.     else if (psz[0] == '+')                    // Extract sign
  236.         psz++;
  237.     else if (psz[0] == '-')
  238.         {
  239.         psz++;
  240.         fMinus = TRUE;
  241.         }
  242.  
  243.     while (psz[0] && psz[0] == '0')        // Remove leading zeroes 
  244.         {
  245.         cZero++;
  246.         psz++;
  247.         }
  248.  
  249.     while (psz[0] && isascii(psz[0]) &&
  250.     (isdigit(psz[0]) || (fHex && isxdigit(psz[0]))))
  251.         {                                            // Count digits and move them 
  252.         ++cDigits;                                // to temporary buffer 
  253.         if (cDigits >= 11 || (fHex && cDigits > 8))
  254.             return FALSE;
  255.         *pszBuf++ = *psz++;
  256.         }
  257.     *pszBuf = '\0';                            // Null terminate buffer
  258.  
  259.     if (!cDigits && !cZero)                    // Must have at least one digit 
  260.         return FALSE;
  261.  
  262.     psz = strskipws(psz);
  263.  
  264.     if (psz[0])                                    // Nothing allowed after last digit 
  265.         return FALSE;                            //  except whitespace 
  266.  
  267.     if (cDigits == 10 && !fHex)            // Check if out of range 
  268.         if (strcmp(szBuf, pszLong) > 0)
  269.             return FALSE;
  270.  
  271.     if (pl)
  272.         if (cDigits)                            // Only leading zeroes 
  273.             {
  274.             if (fHex)
  275.                 pl[0] = (long)strtoul(szBuf, NULL, 16);
  276.             else 
  277.                 pl[0] = atol(szBuf);
  278.  
  279.             if (fMinus)
  280.                 pl[0] = -pl[0];
  281.             }
  282.     return TRUE;
  283. }
  284.  
  285.  
  286. //----------------------------------------------------------------------------
  287. //   Description:    Extract an signed short value from a string. 
  288. //    Parameters:    psz            String to validate.
  289. //                        ps             Pointer to store short value at. If null, don't
  290. //                                        save value.
  291. //       Returns:    TRUE if string represented a valid short.
  292. //----------------------------------------------------------------------------
  293. BOOL FN_E strvalidshort(PCSZ pcsz, PSHORT ps)
  294. {
  295.     LONG l;
  296.  
  297.     if (!strvalidlong(pcsz, &l))
  298.         return FALSE;
  299.  
  300.     if (l < (LONG)MIN_SHORT || l > (LONG)MAX_SHORT)
  301.         return FALSE;
  302.  
  303.     if (ps)
  304.         ps[0] = (SHORT)l;
  305.  
  306.     return TRUE;
  307. }
  308.  
  309.  
  310. //----------------------------------------------------------------------------
  311. //   Description:    Extract an unsigned long value from a string.
  312. //    Parameters:    psz            String
  313. //                        pul            Pointer to store long value at. If null, don't
  314. //                                        save value. Contains the value 0L if the
  315. //                                        return value is FALSE.
  316. //       Returns:    TRUE if string represented a valid unsigned long.
  317. //----------------------------------------------------------------------------
  318. BOOL FN_E strvalidulong(PCSZ psz, PULONG pul)
  319. {
  320. static PSZ pszULong = "4294967295";
  321.  
  322.     SIZET cDigits = 0;
  323.     SIZET cZero = 0;
  324.     BOOL fHex = FALSE;
  325.     CHAR szBuf[11];
  326.     PSZ pszBuf = szBuf;
  327.  
  328.     if (pul)
  329.         pul[0] = 0L;
  330.  
  331.     if (!psz || !psz[0])                        // String must not be empty
  332.         return FALSE;
  333.  
  334.     psz = strskipws(psz);                    // Skip leading whitespace 
  335.     if (psz[0] == '0' && toupper(psz[1]) == 'X')
  336.         {
  337.         fHex = TRUE;
  338.         psz += 2;
  339.         }
  340.     while (psz[0] && psz[0] == '0')        // Remove leading zeroes 
  341.         {
  342.         cZero++;
  343.         psz++;
  344.         }
  345.     while (psz[0] && isascii(psz[0])
  346.     && (isdigit(psz[0]) || (fHex && isxdigit(psz[0]))))
  347.         {                                            // Count digits and move them 
  348.         ++cDigits;                                // to temporary buffer 
  349.                                                       // Too many digits for a valid ulong 
  350.         if (cDigits >= 11 || (fHex && cDigits > 8))
  351.             return FALSE;
  352.  
  353.         *pszBuf++ = *psz++;
  354.         }
  355.     *pszBuf = '\0';
  356.     if (!cDigits && !cZero)
  357.         return FALSE;                            // Must have at least one digit
  358.  
  359.     psz = strskipws(psz);
  360.     if (psz[0])                                    // Nothing allowed after last digit 
  361.         return FALSE;                            //  except whitespace 
  362.  
  363.     if (cDigits == 10)                        // Check if out of range 
  364.         if (strcmp(szBuf, pszULong) > 0)
  365.             return FALSE;
  366.  
  367.     if (pul)
  368.         if (cDigits)
  369.             {
  370.             if (fHex)
  371.                 pul[0] = strtoul(szBuf, NULL, 16);
  372.             else 
  373.                 pul[0] = strtoul(szBuf, NULL, 10);
  374.             }
  375.     return TRUE;
  376. }
  377.  
  378.  
  379. //----------------------------------------------------------------------------
  380. //   Description:    Extract an unsigned integer value from a string. 
  381. //    Parameters:    psz            Pointer to string.
  382. //                        pus            Pointer to store short value at. If null, don't
  383. //                                        save value.
  384. //       Returns:    TRUE if string represented a valid unsigned short
  385. //----------------------------------------------------------------------------
  386. BOOL FN_E strvalidushort(PCSZ psz, PUSHORT pus)
  387. {
  388.     ULONG ul;
  389.  
  390.     if (!strvalidulong(psz, &ul))
  391.         return FALSE;
  392.  
  393.     if (ul > (ULONG)MAX_USHORT)
  394.         return FALSE;
  395.  
  396.     if (pus)
  397.         pus[0] = (USHORT)ul;
  398.  
  399.     return TRUE;
  400. }
  401. //----------------------------------------------------------------------------
  402. //------------------------------- End of File --------------------------------
  403. //----------------------------------------------------------------------------
  404.  
  405.